/**   
* @Title: RedisConfiguration.java
* @Package me.crawler.config
* @Description: TODO
* @author xaoyaoyao
* @date 2018年10月18日 下午5:30:46
* @version V1.0   
*/
package me.crawler.config;

import java.lang.reflect.Method;
import java.time.Duration;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;

import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName: RedisConfiguration
 * @Description: TODO
 * @author xaoyaoyao
 * @date 2018年10月18日 下午5:30:46
 * 
 */
@Slf4j
@Configuration
@EnableCaching(proxyTargetClass = true)
public class RedisConfiguration extends CachingConfigurerSupport {

	private Duration timeToLive = Duration.ZERO;

	public void setTimeToLive(Duration timeToLive) {
		this.timeToLive = timeToLive;
	}

	@Bean
	public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
		timeToLive = null == timeToLive || timeToLive == Duration.ZERO ? Duration.ofMinutes(60) : timeToLive;
		RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(timeToLive)
				.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
				.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()));
		RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).cacheDefaults(defaultCacheConfig).transactionAware().build();
		log.debug("自定义RedisCacheManager加载完成");
		return redisCacheManager;
	}

	@Bean(name = "redisTemplate")
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
		redisTemplate.setConnectionFactory(redisConnectionFactory);
		redisTemplate.setKeySerializer(keySerializer());
		redisTemplate.setHashKeySerializer(keySerializer());
		redisTemplate.setValueSerializer(valueSerializer());
		redisTemplate.setHashValueSerializer(valueSerializer());
		return redisTemplate;
	}

	private RedisSerializer<String> keySerializer() {
		return new StringRedisSerializer();
	}

	private RedisSerializer<Object> valueSerializer() {
		return new FastJsonRedisSerializer<Object>(Object.class);
	}

	@Bean
	public KeyGenerator keyGenerator() {
		return new KeyGenerator() {
			@Override
			public Object generate(Object o, Method method, Object... objects) {
				StringBuilder sb = new StringBuilder();
				sb.append(o.getClass().getName()).append(".");
				sb.append(method.getName()).append(".");
				try {
					if (objects.length > 0) {
						sb.append("#");
					}
					String sp = "";
					for (Object object : objects) {
						sb.append(sp);
						if (object == null) {
							sb.append("NULL");
						} else {
							sb.append(object.toString());
						}
						sp = ".";
					}
				} catch (Exception e) {
					log.error(e.getMessage(), e);
				}
				log.info(">>>>>>>> 自定义生成redis-key完成，keyGenerator=" + sb.toString());
				return sb.toString();
			}
		};
	}
}
